package com.zhss.service;

import com.zhss.demo.ServiceAInterface;
import com.zhss.demo.User;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;

//import org.springframework.web.bind.annotation.PathVariable;
//import org.springframework.web.bind.annotation.RequestBody;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestMethod;
//import org.springframework.web.bind.annotation.RequestParam;

// 这个FeignClient里面的名字，就是你要调用的那个服务的名字
// 什么叫做声明式的方式，就是不用写代码，直接接口 +注解就搞定了，直接就可以访问别的服务
// 你用了feign之后，说实话，我提前给你剧透一下，spring cloud直接将feign和ribbon整合在一起了
// feign + ribbon + eureka都是整合在一起的
// feign发起请求的时候，都是会交给ribbon的LoadBalancer去进行负载均衡的
// 我们会感觉到，跟之前研究的ribbon整合eureka的负载均衡的原理还不是太一样，我们后面通过源码来看看
// feign + ribbon + eureka是如何整合在一起的

// 疑问来了，我希望的是说，ServiceB要调用ServiceA
// 我希望的是说，我连这个下面的一堆接口都不用自己定义，ServiceA直接提供给我这一票东东
// 这里其实是有重复性的劳动在里面的，其实每个接口的一堆定义和注解，都是由ServiceA搞定就可以了
// 不需要ServiceB重复的定义一遍

// 我只是说，我要访问ServiceA，但是人家ServiceA里面定义了哪些接口，哪些参数，都不用你管了
// 这里不用ServiceB把接口的定义重新写一遍了，直接用人家jar包里提供的就ok了
@FeignClient(value = "ServiceA", fallbackFactory = ServiceAClient.ServiceAClientHystrixFallbackFactory.class)
public interface ServiceAClient extends ServiceAInterface {

    @Component
    class ServiceAClientHystrixFallbackFactory implements FallbackFactory<ServiceAClient> {
        private Logger logger = LoggerFactory.getLogger(ServiceAClientHystrixFallbackFactory.class);

        @Override
        public ServiceAClient create(Throwable throwable) {
            logger.error("fallback reason:{}", throwable.getMessage());

            return new ServiceAClient() {
                @Override
                public String sayHello(Long id, String name, Integer age) {
                    logger.warn("sayHello 降级方法");
                    return "sayHello 降级方法";
                }

                @Override
                public String createUser(User user) {
                    logger.warn("createUser 降级方法");
                    return "createUser 降级方法";
                }

                @Override
                public String updateUser(Long id, User user) {
                    logger.warn("updateUser 降级方法");
                    return "updateUser 降级方法";
                }

                @Override
                public String deleteUser(Long id) {
                    logger.warn("deleteUser 降级方法");
                    return "sayHedeleteUserllo 降级方法";
                }

                @Override
                public User getById(Long id) {
                    logger.warn("getById 降级方法");
                    return null;
                }
            };
        }
    }
}